package model.dominio;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.PostPersist;
import javax.persistence.PostUpdate;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import model.dao.DaoBase;

@Entity
@Table(name = "locacao")
public class Locacao implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(unique = true, nullable = false)
    private int codigo = 0;
    @Column
    private Long kmSaida;
    @Column
    private Long kmEntrada;
    @Column(name = "data_saida")
    @Temporal(TemporalType.DATE)
    private Calendar dataSaida;
    @Column(name = "data_devolucao")
    @Temporal(TemporalType.DATE)
    private Calendar dataDevolucao;
    @Column
    private Integer previsaoDias;
    @JoinColumn(name = "codigo_veiculo", referencedColumnName = "codigo")
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private Veiculo veiculo;
    @JoinColumn(name = "codigo_cliente", referencedColumnName = "codigo")
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private Cliente cliente;
    @Column
    private int tipoLocacao;
    @Column
    private double valorLocacao;
    @Temporal(TemporalType.TIMESTAMP)
    private Calendar data_ultima_alteracao;
    @JoinColumn(name = "codigo_usuario", referencedColumnName = "codigo")
    @ManyToOne(optional = true, fetch = FetchType.EAGER)
    private Usuario usuario;
    @ManyToMany(targetEntity = model.dominio.Motorista.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(name = "motorista_locacao", joinColumns = {
        @JoinColumn(name = "codigo_locacao")}, inverseJoinColumns = {
        @JoinColumn(name = "condigo_motorista")})
    private List<Motorista> motoristas = new ArrayList<Motorista>();

    public Locacao() {
        this.cliente = new Cliente(null, null);
        this.veiculo = new Veiculo(null, null, null);
    }

    /**
     * @return the kmSaida
     */
    public Long getKmSaida() {
        return kmSaida;
    }

    /**
     * @param kmSaida the kmSaida to set
     */
    public void setKmSaida(Long kmSaida) {
        this.kmSaida = kmSaida;
    }

    /**
     * @return the kmEntrada
     */
    public Long getKmEntrada() {
        return kmEntrada;
    }

    /**
     * @param kmEntrada the kmEntrada to set
     */
    public void setKmEntrada(Long kmEntrada) {
        this.kmEntrada = kmEntrada;
    }

    /**
     * @return the dataSaida
     */
    public Calendar getDataSaida() {
        return dataSaida;
    }

    /**
     * @param dataSaida the dataSaida to set
     */
    public void setDataSaida(String dataSaida) {
        try {
            String aux[] = dataSaida.split("/");
            this.dataSaida = (Calendar) Calendar.getInstance().clone();
            this.dataSaida.set(Integer.parseInt(aux[2]), Integer.parseInt(aux[1]), Integer.parseInt(aux[0]));
        } catch (Exception e) {
            dataSaida = null;
        }
    }

    /**
     * @return the dataDevolucao
     */
    public Calendar getDataDevolucao() {
        return dataDevolucao;
    }

    /**
     * @return the dataDevolucao
     */
    public long getKmRodados() {
        return kmEntrada - kmSaida;
    }

    /**
     * @param dataDevolucao the dataDevolucao to set
     */
    public void setDataDevolucao(String dataDevolucao) {
        try {
            String aux[] = dataDevolucao.split("/");

            this.dataDevolucao = (Calendar) Calendar.getInstance().clone();
            this.dataDevolucao.set(Integer.parseInt(aux[2]), Integer.parseInt(aux[1]), Integer.parseInt(aux[0]));
        } catch (Exception e) {
            dataSaida = null;
        }
    }

    /**
     * @return the previsaoDias
     */
    public Integer getPrevisaoDias() {
        return previsaoDias;
    }

    /**
     * @param previsaoDias the previsaoDias to set
     */
    public void setPrevisaoDias(Integer previsaoDias) {
        this.previsaoDias = previsaoDias;
    }

    /**
     * @return the veiculo
     */
    public Veiculo getVeiculo() {
        return veiculo;
    }

    /**
     * @param veiculo the veiculo to set
     */
    public void setVeiculo(Veiculo veiculo) {
        this.veiculo = veiculo;
    }

    /**
     * @return the cliente
     */
    public Cliente getCliente() {
        return cliente;
    }

    /**
     * @param cliente the cliente to set
     */
    public void setCliente(Cliente cliente) {
        this.cliente = cliente;
    }

    /**
     * @return the codigo
     */
    public int getCodigo() {
        return codigo;
    }

    /**
     * @param codigo the codigo to set
     */
    public void setCodigo(int codigo) {
        this.codigo = codigo;
    }

    /**
     * @return the tipoLocacao
     */
    public int getTipoLocacao() {
        return tipoLocacao;
    }

    /**
     * @return the motoristas
     */
    public List<Motorista> getMotoristas() {
        return motoristas;
    }

    /**
     * @param tipoLocacao the tipoLocacao to set
     */
    public void addMotorista(Motorista motorista) {
        motoristas.add(motorista);
    }

    /**
     * @param tipoLocacao the tipoLocacao to set
     */
    public void remMotorista(String cnh) {
        for (int i = 0; i < motoristas.size(); i++) {
            if (motoristas.get(i).getCnh().equals(cnh)) {
                motoristas.remove(i);
                break;
            }
        }
    }

    /**
     * @param tipoLocacao the tipoLocacao to set
     */
    public void setTipoLocacao(int tipoLocacao) {
        this.tipoLocacao = tipoLocacao;
    }

    /**
     * @return the data_ultima_alteracao
     */
    public Calendar getData_ultima_alteracao() {
        return data_ultima_alteracao;
    }

    /**
     * @param data_ultima_alteracao the data_ultima_alteracao to set
     */
    public void setData_ultima_alteracao(Calendar data_ultima_alteracao) {
        this.data_ultima_alteracao = data_ultima_alteracao;
    }

    /**
     * @return the usuario
     */
    public Usuario getUsuario() {
        return usuario;
    }

    /**
     * @param usuario the usuario to set
     */
    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    public int diffDatas() {
        long diff = dataDevolucao.getTimeInMillis() - dataSaida.getTimeInMillis();

        return (int) diff / (1000 * 60 * 60 * 24);
    }

    public double calcularValorLocacao() {
        long diffKms = this.kmEntrada - this.kmSaida;
        int dias = diffDatas();
        if (dias == 0) {
            dias = 1;
        }

        double valorLocacao = 0;
        if (this.tipoLocacao == 1) {
            valorLocacao = diffKms * veiculo.getTipo().getPrecoKm();
            valorLocacao += dias * veiculo.getTipo().getPrecoBase();
        } else {
            valorLocacao = dias * veiculo.getTipo().getTaxaUnica();
        }
        if (valorLocacao > veiculo.getTipo().getPrecoBase()) {
            this.valorLocacao=valorLocacao;
            return valorLocacao;
        } else {
            return 0;
        }
    }
    
    @PostPersist
    public void gerarLogCad(){
        Logg logg=new Logg();
        logg.setCodigo_objeto(this.codigo);
        logg.setAcao(new AcaoSistema(18));
        logg.setData_hora(this.data_ultima_alteracao);
        logg.setUsuario(this.usuario);
        new DaoBase().salvar(logg);
    }
    @PostUpdate
    public void gerarLogAlt(){
        Logg logg=new Logg();
        logg.setCodigo_objeto(this.codigo);
        logg.setAcao(new AcaoSistema(19));
        logg.setData_hora(this.data_ultima_alteracao);
        logg.setUsuario(this.usuario);
        new DaoBase().salvar(logg);
    }
}
